﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Index;

namespace Lucandra.Net
{
    internal class CachedTermDocs : TermDocs
    {
        protected LucandraTermInfo termInfo;
        protected LucandraTermInfo.LucandraTermInfoDocument[] termDocuments;
        protected int documentPosition;
        protected bool isClosed;

        protected LucandraReader @LucandraReader { get; private set; }

        public CachedTermDocs(LucandraReader reader, LucandraTermInfo termInfo)
        {
            this.termInfo = termInfo;
            this.termDocuments = termInfo.Documents.ToArray();
            this.LucandraReader = reader;
        }

        #region TermDocs Members

        public void Seek(Term term)
        {
            if (!this.termInfo.GetTerm().Equals(term))
                throw new LucandraException("Tried to seek on CachedTermDocs with incorrect term.");

            this.documentPosition = -1;
            this.isClosed = false;
        }

        public void Seek(TermEnum termEnum)
        {
            throw new InvalidOperationException("CachedTermDocs does not support seeking on a TermEnum.");

            var lucandraTermEnum = termEnum as LucandraTermEnum;
            this.termDocuments = lucandraTermEnum.GetTermInfoDocuments().ToArray();
            this.documentPosition = -1;
            this.isClosed = false;
        }

        public int Doc()
        {
            if (this.documentPosition == -1)
                this.documentPosition = 0;

            string documentID = this.termDocuments[this.documentPosition].DocumentID;
            return this.LucandraReader.GetDocumentNumberFromDocumentID(documentID);
        }

        public int Freq()
        {
            if (this.documentPosition == -1)
                this.documentPosition = 0;

            return this.termDocuments[this.documentPosition].Frequency;
        }

        public bool Next()
        {
            if (this.termDocuments == null || this.documentPosition == this.termDocuments.Length - 1)
            {
                this.isClosed = true;
                return false;
            }

            this.documentPosition++;
            return true;
        }

        public int Read(int[] docs, int[] freqs)
        {
            if (this.isClosed)
                return 0;

            int i = 0;
            for (; this.termDocuments != null && this.documentPosition < this.termDocuments.Length && i < docs.Length; i++)
            {
                docs[i] = this.Doc();
                freqs[i] = this.Freq();
                if (!this.Next())
                {
                    i++;
                    break;
                }
            }

            return i;
        }

        public bool SkipTo(int target)
        {
            while (target > this.Doc())
            {
                if (!this.Next())
                    return false;
            }

            return true;
        }

        public void Close()
        {
            this.termInfo = null;
            this.termDocuments = null;
            this.documentPosition = -1;

            this.LucandraReader = null;
            this.isClosed = true;
        }

        #endregion
    }
}
